package com.lovi.search.service.impl;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lovi.clients.ProductClient;
import com.lovi.doc.ProductDoc;
import com.lovi.param.ProductSearchParam;
import com.lovi.pojo.Product;
import com.lovi.search.service.SearchService;
import com.lovi.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.cert.ocsp.Req;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 由于我们的数据已经同步完成了，所以我们直接在es库当中查询数据即可!
 */
@Slf4j
@Service
public class SearchServiceImpl implements SearchService {

    //调用es客户端
    @Autowired
    private RestHighLevelClient client;

    /**
     * 商品搜索
     * @param productSearchParam
     * @return
     */
    @Override
    public R search(ProductSearchParam productSearchParam) throws JsonProcessingException {

        SearchRequest searchRequest = new SearchRequest("product");

        if (StringUtils.isEmpty(productSearchParam.getSearch())){
            //如果为null,查询全部
            searchRequest.source().query(QueryBuilders.matchAllQuery());
        }else{
            //不为空 all字段进行搜索
            searchRequest.source().query(QueryBuilders.matchQuery("all",productSearchParam.getSearch()));
        }

        //设置分页参数
        searchRequest.source().from((productSearchParam.getCurrentPage()-1)*productSearchParam.getPageSize());
        searchRequest.source().size(productSearchParam.getPageSize());

        SearchResponse response = null;
        try {
            response = client.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw  new RuntimeException(e);
        }

        //结果集解析
        //获取集中的结果
        SearchHits hits = response.getHits();
        //获取符合的数量
        long total = hits.getTotalHits().value;

        SearchHit[] items = hits.getHits();

        List<ProductDoc> productDocList = new ArrayList<>();
        ObjectMapper objectMapper = new ObjectMapper();

        for (SearchHit item : items) {
            //获取单挑json数据
            String json = item.getSourceAsString();
            ProductDoc productDoc = objectMapper.readValue(json, ProductDoc.class);
            productDocList.add(productDoc);
        }

        return R.ok(null,productDocList,total);
    }

    /**
     * es更新和插入及时更新！
     * @param product
     * @return
     * @throws IOException
     */
    @Override
    public R save(Product product) throws IOException {
        //创建一个插入/更新索引请求，product_id为查询索引，当我们es库数据当中不存在这个索引，就执行插入，存在就执行更新操作
        IndexRequest indexRequest
                = new IndexRequest("product").id(product.getProductId().toString());

        ProductDoc productDoc = new ProductDoc(product);
        //通过json的形式把更新/覆盖的值放入es库当中
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(productDoc);

        indexRequest.source(json, XContentType.JSON);
        client.index(indexRequest, RequestOptions.DEFAULT);
        log.info("SearchServiceImpl.save 结果为->{}","es更新和插入更新成功" );

        return R.ok("es数据同步成功！");
    }

    /**
     * es 商品删除数据同步成功！
     * @param productId
     * @return
     * @throws IOException
     */
    @Override
    public R remove(Integer productId) throws IOException {
        //创建删除索引
        DeleteRequest request = new DeleteRequest("product").id(productId.toString());
        //es库删除对应数据
        client.delete(request, RequestOptions.DEFAULT);
        log.info("SearchServiceImpl.save 结果为->{}","es 商品删除数据同步成功" );
        return R.ok("es数据同步成功！");
    }
}
